import os
import random
import string

from PIL import Image, ImageFont, ImageDraw, ImageFilter


class ImageVerify:
    def __init__(self, width=140, height=40, length=5, size=25):
        """
        画布，即图片数据初始化
        :param width: 图片宽带
        :param height: 图片高度
        :param length: 字符长度
        :param size: 字体大小
        """
        self.width = width
        self.height = height
        self.length = length
        self.size = size

    def random_str(self):
        """
        随机字符串,10个数字和26个大小写字母
        :return:
        """
        source_str = string.ascii_letters + string.digits

        return ''.join(random.sample(source_str, self.length))  # sample返回的是列表，join转字符串

    def random_color(self, start=0, end=255):
        """
        设置干扰项，1.颜色干扰，随机颜色RGB
        :param start: 颜色起始值
        :param end: 颜色结束值
        :return: tuple元组(R,G,B)
        """
        res = (random.randint(0, 255) for i in range(3))
        return tuple(res)

    def random_lines(self, draw):
        """
        设置干扰项，2。绘制干扰线，两点决定一条线，一个点(x,y)决定
        :param draw: 画笔对象
        :return:
        """
        for i in range(self.length):  # 字符长度绝对线条数量，看情况
            # 随机拿到两点
            lines = [(random.randint(0, self.width), random.randint(0, self.height)) for i in range(2)]
            draw.line(list(lines), fill=self.random_color(), width=1)  # 用画笔画线，width为线的宽度

    def random_points(self, draw, rate):
        """
        设置干扰项，3.绘制干扰点
        :param draw: 画笔对象
        :param rate: 点的出现频率值
        :return:
        """
        for x in range(self.width):  # x轴取值
            for y in range(self.height):  # y轴取值
                if random.randint(0, 100) < rate:  # 控制概率
                    draw.point((x, y), fill=self.random_color())

    def image_code(self):
        """
        生成验证码图片
        :return:
        """
        # 创建画布Image对象，画布(光的三原色红绿蓝，图片宽和高，红绿蓝数值设置)
        image = Image.new('RGB', (self.width, self.height), (255, 255, 255))

        # 创建字体font对象
        file = os.path.dirname(os.path.abspath(__file__))  # 路径拼接，前面代表文件目录名，后面代表当前文件的绝对路径
        font = ImageFont.truetype(f'{file}/HYYakuHei-85W.ttf', self.size)

        # 创建画笔draw对象，画笔画在画布上
        draw = ImageDraw.Draw(image)

        # 生成随机字符串
        code = self.random_str()

        # 将随机生成的字符串用画笔逐个的画在画布上
        for i in range(self.length):
            # 将验证码中每个字符在x，y轴坐标开始，用font字体画出，画笔用fill指定颜色
            draw.text((25 * i, 3), code[i], font=font, fill=self.random_color(end=100))  # fill里的颜色数值可写可不写

        # 用画笔画干扰线
        self.random_lines(draw)

        # 用画笔画干扰点
        self.random_points(draw, 10)

        # 最后的模糊滤波过滤
        # image = image.filter(ImageFilter.BLUR)

        return image, code  # 返回图形，和验证码


# if __name__ == '__main__':  # 测试当前文件
#     imgVerify = ImageVerify()  # 实例化得到一个对象
#     img, code = imgVerify.image_code()  # 通过对象去调用方法
#     with open('test_img.png', 'wb') as f:  # 以文件的形式默认保存在当前文件夹里，图片是二进制的，即wb
#         img.save(f)  # 保存
